import { computed, ref, watchEffect, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import FormatFunctions from './lib/FormatFunctions';

import {
  usePropsTwoWayValues,
} from 't/common/utils';

export const useDataGridProps = {
  showAutoFilterRow: Boolean,
  allowColumnMoving: {
    type: Boolean,
    default() {
      return true;
    },
  },
  allowColumnResizing: {
    type: Boolean,
    default() {
      return false;
    },
  },
  allowColumnWarp: Boolean,
  columnsFilter: Boolean,
  allowFilter: Boolean,
  showStriped: {
    type: Boolean,
    default() {
      return true;
    },
  },
  allowSort: {
    type: Boolean,
    default() {
      return false;
    },
  },
  // draggable: Boolean,
  // draggable_columns: Boolean,
  showRowNumber: {
    type: Boolean,
    // default() {
    //   return true;
    // },
  },
  showFixedShadow: {
    type: Boolean,
    default() {
      return false;
    },
  },
  hideHeader: Boolean,
};

export const useDataGridOptsProps = {
  rows: {
    type: [Array, String],
    default() {
      return [];
    },
  },
  isDev: {
    type: Boolean,
    default() {
      return false;
    },
  },
  optColumns: {
    type: [Array, String],
    default() {
      return [];
    },
  },
  optCmdColConfig: {
    type: Object,
    default() {
      return {};
    },
  },
  rowsNumber: {
    type: [Number, String],
  },
  pageIndex:{
    type: [Number, String],
  },
  pageSize: {
    type: [Number, String],
  },
  fillMode: {
    type: String,
    default() {
      return 'auto';
    },
  },
  fillMarginBottom: {
    type: String,
    default() {
      return '';
    },
  },
  height: {
    type: String,
    default() {
      return '500px';
    },
  },
  // cellClickInfo: [Object, String],
  enableCmdCol: [Boolean, String],
  cmdColConfig: [Object, String],
  columnLinkFormat: Function,
  cmdColClick: Function,
  colCommandVisible: Function,
  colDataFormat: Function,
};

export function zipObject(keys, values) {
  const result = {};

  for (let i = 0; i < keys.length; i++) {
    result[keys[i]] = values[i];
  }

  return result;
}

function colFormat(cellInfo, col) {
  let formatFunc = FormatFunctions[col.dataFormat.FormatType];
  return formatFunc ? formatFunc(cellInfo, col) : void 0;
}

const mockColumns = [
  {
    headerClasses: `ignore-elements`,
    __isShow: true,
    name: 'code',
    field: 'code',
    label: '编号',
  },
  {
    headerClasses: `ignore-elements`,
    __isShow: true,
    name: 'name',
    field: 'name',
    label: '名称',
  },
  {
    headerClasses: `ignore-elements`,
    __isShow: true,
    name: 'col3',
    field: 'col3',
    label: '字段A',
  },
  {
    headerClasses: `ignore-elements`,
    __isShow: true,
    name: 'col4',
    field: 'col4',
    label: '字段B',
  },
];

function getCols(props) {
  const { t } = useI18n({ useScope: 'global' });
  let propsColumns = props.columns
    ? props.columns
    : props.optColumns?.sort((a, b) => {
      let aFC = a.fixedColumn;
      let bFC = b.fixedColumn;
      aFC = aFC == 'left' ? -1 : aFC == 'right' ? 1 : 0;
      bFC = bFC == 'left' ? -1 : bFC == 'right' ? 1 : 0;
      return aFC - bFC;
    });
  let cols = propsColumns?.map((col, index) => {
    let { dataField, caption, alignment, width, ValueInfo_caption } = col;
    if (ValueInfo_caption?.ReferenceExpr) {
      caption = t(ValueInfo_caption?.ReferenceExpr, caption);
    }
    let sortable = props.allowSort;
    let dataType = col.dataType?.toLowerCase();
    let format;
    if (col.dataFormat) {
      format = (val, row) => {
        let formatValue = colFormat({ value: val }, col);
        if (formatValue === void 0) {
          if (props.colDataFormat) {
            return props.colDataFormat(col, col.dataFormat, val, row) || val;
          } else {
            return val;
          }
        } else {
          return formatValue;
        }
      };
    }

    if (!alignment) {
      alignment = 'left';
      switch (dataType) {
        case 'int':
        case 'decimal':
          alignment = 'right';
          break;
      }
    }

    if (!width) {
      switch (dataType) {
        case 'date':
        case 'time':
        case 'datetime':
          width = '200px';
          break;
      }
    }
    if (width && false == isNaN(+width)) {
      width = width + 'px';
    }
    let headerStyle = [
      width && `min-width:${width};max-width:${width};width:${width}`,
      // width && `width:${width}`,
      // width
      //   ? `min-width:${width};max-width:${width};width:${width}`
      //   : index == propsColumns.length - 1
      //     ? `width:100%`
      //     : `width:100%`,
    ].join(';');
    return {
      __isShow: col.isShow,
      optCol: col,
      // 唯一的 id
      // 某列数据的标识
      // 会在 pagination.sortBy，"body-cell-[name]，slot 等地方使用。
      name: dataField,

      // 头部的标签
      label: caption,

      // 决定此列数据使用对象中的哪个字段
      field: dataField,
      // 或者 field: row => row.some.nested.prop,

      // (可选的)  如果我们使用 visible-columns 属性，那么这个列将始终可见
      // required: true,

      // (可选的) 对齐方式
      align: alignment,

      // (可选的) 告诉 QTable，您想要这个列是可排序的。
      // sortable: sortable,
      /*
    // (可选的) 自定义排序函数
    sort: (a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10),
    // 函数返回值：
    //   * 小于 0 表示 a 小于 b，排序时 a 在 b 前面。
    //   * 等于 0，则 a 和 b 的位置保持不变，对其他不同的元素进行排序。
    //   * 大于 0 表示 a 大于 b，排序时 a 在 b 后面。

    // (可选的) 重写 'column-sort-order' 属性;
    // 设置排序顺序:
    // 'ad' (ascending-descending)表示升序降序
    // 'da' (descending-ascending)表示降序排序
    sortOrder: 'ad', // 或者 'da'
    */
      // sortOrder: 'ad', // 或者 'da'

      // (可选的) 您可以使用一个函数来格式化数据
      // ...{ format },
      format,

      // format: (val, row) => `${val}%`,
      // 另一个格式化示例：
      // format: val => val
      //   ? /* val 值为 true 则使用勾选状态的 Unicode 字符：☑ */ "\u2611"
      //   : /* 否则使用未选中状态的 Unicode 字符：☐ */ "\u2610",

      classes: [
        col.fixedColumn && !props.disableFixedColumn
          ? `fixed-column-${col.fixedColumn}`
          : '',
        // 'white-space-wrap',
      ].join(' '),
      headerClasses:
        col.fixedColumn && !props.disableFixedColumn
          ? `fixed-column-${col.fixedColumn}`
          : '',
      headerStyle,
      style: props.hideHeader ? headerStyle : '',
      /*
    // body td:
    style: 'width: 500px',
    // 或者使用一个函数 --> style: row => ... (return String/Array/Object)
    classes: 'my-special-class',
    // 或者使用一个函数 --> classes: row => ... (return String)

    // header th:
    headerStyle: 'width: 500px',
    headerClasses: 'my-special-class'
    */
      // style: 'width: 500px',
      // headerStyle: headerStyle,
    };
  });

  if (props.isDev && cols.length == 0) {
    cols = mockColumns;
  }

  return cols;
}
function buildColumns(props) {
  // return computed(() => {
  //   return getCols(props)
  // });
  return ref(getCols(props));
}

export function getVisibleColumns(props) {
  // alert('getVisibleColumns');
  console.log('getVisibleColumns');
  let returnValue = [
    ...(props.visibleColumns
      ? props.visibleColumns
      : props.optColumns
          ?.filter(col => false !== col.isShow)
          .map(col => col.dataField)),
  ];
  if (props.isDev && returnValue.length == 0) {
    returnValue.push(...mockColumns.map(item => item.name));
  }
  props.showRowNumber && returnValue.push('rowNumberColumn');
  props.enableCmdCol && returnValue.push('stickyCmdColumn');

  return returnValue;
}

export function useDataGridOpts(
  props,
  attrs,
  emit,
  expose,
  slots,
  {
    bodyCellLink,
    bodyCellEnum,
    bodyCellBoolean,
    bodyCellDate,
    bodyCellCustomContent,
    bodyCellCharts,
  },
) {
  let cellSlot = {};
  props.optColumns?.map(col => {
    let { dataField, caption, alignment } = col;

    const dataType = col.dataType?.toLowerCase();
    switch (dataType) {
      case 'date':
      case 'datetime':
      case 'timestamp':
        if (!col?.dataFormat?.FormatType) {
          cellSlot[`body-cell-${col.dataField}`] = bodyCellDate;
        }

        break;
      case 'boolean':
        cellSlot[`body-cell-${col.dataField}`] = bodyCellBoolean;
        break;
    }

    if (col.linkFormat) {
      cellSlot[`body-cell-${col.dataField}`] = bodyCellLink;
    }

    if (
      col.enumDisp &&
      col.enumDisp.showMode &&
      col.enumDisp.enumRanges &&
      col.enumDisp.enumRanges.length > 0
    ) {
      cellSlot[`body-cell-${col.dataField}`] = bodyCellEnum;
    }

    if (col.customCellContent) {
      cellSlot[`body-cell-${col.dataField}`] = bodyCellCustomContent;
    }

    if (col.chartOptions?.type) {
      cellSlot[`body-cell-${col.dataField}`] = bodyCellCharts;
    }
  });

  console.log('fasr-data-grid', 'useDataGridOpts');
  // const columns = ref(buildColumns(props));
  const columns = buildColumns(props);

  const computedColumns = computed(() => columns.value);

  const computedVisibleColumns = ref(getVisibleColumns(props));

  const computedPagination = computed({
    get() {
      return props.pagination
        ? props.pagination
        : {
            sortBy: null,
            descending: false,
            page: props.pageIndex || 1,
            rowsPerPage: props.hidePagination ? 0 : props.pageSize || 50,
            rowsNumber: props.rowsNumber,
          };
    },
    set(val) {
      emit('update:pagination', val);
    },
  });

  const rowNumberColumn = computed(() => {
    return {
      headerClasses: `ignore-elements ${!props.disableFixedColumn ? 'fixed-column-left' : ''}`,
      classes: !props.disableFixedColumn ? `fixed-column-left` : '',
      align: 'center',
      name: 'rowNumberColumn',
      headerStyle:
        'min-width: 50px;max-width: 50px;width: 50px;padding-left: 5px;padding-right: 5px;',
      style: 'padding-left: 0px;padding-right: 0px;',
    };
  });

  const { t } = useI18n({ useScope: 'global' });
  const stickyCmdColumn = computed(() => {
    const { columnConf, commands } = props.optCmdColConfig;
    let stickyCmdColumn;
    const isPC =  window?.isPC?.();
    if (commands?.length > 0) {
      let width = columnConf?.width;
      width += 8 + 4; /** 补充操作列固定列引用 */
      stickyCmdColumn = {
        headerClasses: `ignore-elements ${isPC ? "sticky" : ""} ${columnConf.fixedPosition}`,
        classes: `${isPC ? "sticky" : ""} ${columnConf.fixedPosition}`,
        // classes:
        //   columnConf.fixedPosition == 'right' ? 'stickyLast' : 'stickyFirst',
        align: 'center',
        name: 'stickyCmdColumn',
        sortable: false,
        headerStyle: [
          'text-align: left; padding-left: 24px;',
          width && `min-width:${width}px;max-width:${width}px;width:${width}px`,
        ].join(';'),
        style: [
          'text-align: left; padding-left: 24px;',
          width && `min-width:${width}px;max-width:${width}px;width:${width}px`,
        ].join(';'),
        label: t(columnConf?.ValueInfo_caption, columnConf?.caption),
        cmdColConfig: props.optCmdColConfig,
        fixedPosition: columnConf.fixedPosition,
      };
    }
    return stickyCmdColumn;
  });

  return {
    rowNumberColumn,
    stickyCmdColumn,
    columns,
    cellSlot,
    computedVisibleColumns,
    computedColumns,
    computedPagination,
  };
}

export function useOpts(object) {
  const computedOpts = computed(() => {
    let opts = { computedPagination: object.computedPagination };
    for (const key in object) {
      if (Object.hasOwnProperty.call(object, key)) {
        const element = object[key];
        if (element.value !== void 0) {
          let newProp = key.replace('computed', '');
          newProp = newProp.charAt(0).toLowerCase() + newProp.slice(1);
          opts[newProp] = element.value;
        }
      }
    }
    return opts;
  });

  return computedOpts;
}

export default function (props, slots) {
  const hasHeaderSlot = computed(() => {
    return slots.hasOwnProperty('header');
  });
  return {
    hasHeaderSlot,
  };
}
